/*
 * MIT License
 * 
 * Copyright (c) 2017 wen.gu <454727014@qq.com>
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */


#ifndef __MAZE_GENETIC_H__
#define __MAZE_GENETIC_H__

#ifdef __cplusplus
extern "C" {
#endif // __cplusplus


#define POPULATION_SIZE 140
#define CHROMOSOME_LENGTH 35
#define GENE_LENGTH 2

#define CROSSOVER_RARE 0.7

#define MUTATION_RATE  0.001



typedef char gene_t; /** the type of gene */

typedef struct genome_s 
{
//    int gene_length; /** how many bits per gene */
//   int chromosome_length; /** how many count of gene per chromosome */
    gene_t genes[CHROMOSOME_LENGTH]; /** chromosome (consist of a number of genes) */
    double fitness; /** the score of fitness */    
}genome_t;


typedef struct population_s
{
    int pop_size; /** the size of population(how many genomes per population) */
    genome_t genomes[POPULATION_SIZE]; /** the population of genomes */

    double crossover_rate; /** the rate of genome crossover */
    double mutation_rate; /** the rate of genome mutation */

    /** because all genome have the same of gen_length and chromosome length, 
     * so we move them to here from structure of genome_t to save memory */
    int gene_length; /** how many bits per gene */
    int chromosome_length; /** how many count of gene per chromosome */

    //////////////////////////////////////////////////////////////////////////
    int fittest_genome; /**the genome which have best score of fitness */
    double best_fitness_score; /** the best of score of fitness */

    double total_fitness_score; /** the total of all score of fitness */

    int generation; /** mark the count of genetic generation */

    unsigned int is_running; /** 1: running, 0: not. to avoid  endless loop */
}population_t;



/**
*
*@brief  initialize genome
*
*@param  genome [in] pointer to genome.
*@param  chromosome_length [in] how many gene of chromosome
*
*@return none.
*
*@see
*/
void genomeInitialize(genome_t* genome, int chromosome_length);


/**
*
*@brief  decode gene to move step, @see also move_step_e
*
*@param  genome [in] pointer to genome.
*@param  move_steps [in] a array for move steps(array size must >= chromosome length).
*@param  chromosome_length [in] the length of chromosome
*
*@return none.
*
*@see
*/
void genomeDecode(genome_t* genome, int move_steps[], int chromosome_length);


/**
*
*@brief  initialize population
*
*@param  population [in] pointer to population.
*@param  pop_size   [in] how many individuals(genomes) in the population
*@param  gen_length [in] how many bits per gene
*@param  chromosome_length [in] how many genes per chromosome.
*@param  crossover_rate [in] the rate of chromosome crossover.
*@param  mutation_rate  [in] the rate of chromosome mutation. 
*
*@return none.
*
*@see
*/
void populationInitialize(population_t* population, int pop_size,
                          int gene_length, int chromosome_length,
                          double crossover_rate, double mutation_rate);


/**
*
*@brief  get a new epoch of population
*
*@param  population [in] pointer to population.
*
*@return 1: found the exit of maze(got the genome which have the best of fitness score), 0: not found.
*
*@see
*/
unsigned int populationEpoch(population_t* population);






#ifdef __cplusplus
}
#endif // __cplusplus


#endif // !__MAZE_GENETIC_H__

